package com.binc.testspring.common.handler;

import com.binc.testspring.common.annotation.DictCode;
import com.binc.testspring.common.utils.BinaryNumberUtils;
import com.binc.testspring.common.utils.DateUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

public class DefaultDictHandler<T> implements IDictHandler<T> {
    private static final Logger log = LoggerFactory.getLogger(DefaultDictHandler.class);
    private List<DictTypeDto> dictTypeDtos = new ArrayList();

    public DefaultDictHandler() {
    }

    @Override
    public <T> T decode(T source, Set<DictCodeProperty> properties) {
        return source == null ? null : this.convertDict(source, properties);
    }

    @Override
    public void setSource(List<DictTypeDto> source) {
        this.dictTypeDtos = source;
    }

    private <T> T convertDict(T source, Set<DictCodeProperty> properties) {
        BeanWrapper sourceBw = PropertyAccessorFactory.forBeanPropertyAccess(source);
        Iterator var4 = properties.iterator();

        while(true) {
            DictCodeProperty property;
            DictCode dictCode;
            Object fieldValue;
            while(true) {
                if (!var4.hasNext()) {
                    return source;
                }

                property = (DictCodeProperty)var4.next();
                dictCode = property.getDictCode();
                String fieldKey = property.getName();
                if (StringUtils.isNotBlank(dictCode.prop())) {
                    fieldKey = dictCode.prop();
                }

                fieldValue = sourceBw.getPropertyValue(fieldKey);
                if (!StringUtils.isNotBlank(dictCode.format()) || !StringUtils.isNotBlank(dictCode.prop()) || !StringUtils.isBlank(dictCode.code()) && dictCode.conts() != null && dictCode.conts().length > 0) {
                    break;
                }

                try {
                    if (fieldValue != null && fieldValue instanceof Date) {
                        sourceBw.setPropertyValue(property.getName(), DateUtils.formatDate((Date)fieldValue, new Object[]{dictCode.format()}));
                    }

                    if (fieldValue != null && fieldValue instanceof Long) {
                        sourceBw.setPropertyValue(property.getName(), DateUtils.formatDate(new Date((Long)fieldValue), new Object[]{dictCode.format()}));
                    }
                } catch (Exception var18) {
                    log.error(var18.getMessage(), var18);
                    break;
                }
            }

            DictDataDto dictDataDto = null;
            if (StringUtils.isNotBlank(dictCode.code())) {
                DictTypeDto dictTypeDto = null;
                DictCode finalDictCode = dictCode;
                List<DictTypeDto> fetchTypeList = (List)this.dictTypeDtos.stream().filter((item) -> {
                    return item != null && StringUtils.isNotBlank(item.getCode());
                }).filter((item) -> {
                    return finalDictCode.code().equals(item.getCode());
                }).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(fetchTypeList)) {
                    dictTypeDto = (DictTypeDto)fetchTypeList.get(0);
                }

                if (dictTypeDto != null && CollectionUtils.isNotEmpty(dictTypeDto.getDictDataDtos())) {
                    List fieldListValue;
                    if (!(fieldValue instanceof List) && !sourceBw.getPropertyType(property.getName()).isAssignableFrom(List.class)) {
                        Object finalFieldValue = fieldValue;
                        fieldListValue = (List)dictTypeDto.getDictDataDtos().stream().filter((item) -> {
                            return item != null && StringUtils.isNotBlank(String.valueOf(item.getVal()));
                        }).filter((item) -> {
                            return String.valueOf(item.getVal()).equals(String.valueOf(finalFieldValue));
                        }).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(fieldListValue)) {
                            dictDataDto = (DictDataDto)fieldListValue.get(0);
                        }
                    } else {
                        fieldListValue = null;
                        if (!(fieldValue instanceof Long) && !(fieldValue instanceof Integer)) {
                            if (fieldValue instanceof List) {
                                fieldListValue = (List)fieldValue;
                            }
                        } else {
                            fieldListValue = BinaryNumberUtils.splitToInt(Long.parseLong(String.valueOf(fieldValue)));
                        }

                        List newListValue = new ArrayList();
                        if (CollectionUtils.isNotEmpty(fieldListValue)) {
                            List<DictDataDto> fetchList = (List)dictTypeDto.getDictDataDtos().stream().filter((item) -> {
                                return item != null && StringUtils.isNotBlank(String.valueOf(item.getVal()));
                            }).collect(Collectors.toList());
                            Iterator var15 = fieldListValue.iterator();

                            while(var15.hasNext()) {
                                Object value = var15.next();
                                List<DictDataDto> filterList = (List)fetchList.stream().filter((item) -> {
                                    return item.getVal().equals(String.valueOf(value));
                                }).collect(Collectors.toList());
                                if (CollectionUtils.isNotEmpty(filterList)) {
                                    newListValue.add(((DictDataDto)filterList.get(0)).getDictDataName());
                                } else {
                                    newListValue.add(value);
                                }
                            }

                            if (CollectionUtils.isNotEmpty(newListValue)) {
                                dictDataDto = new DictDataDto();
                                dictDataDto.setDictDataName(newListValue);
                                dictDataDto.setVal(fieldValue);
                            }
                        }
                    }
                }
            }

            if (dictDataDto == null && dictCode.conts().length > 0) {
                Class clz = dictCode.conts()[0];
                dictDataDto = this.getContsDictData(fieldValue, dictDataDto, clz, sourceBw, property.getName());
            }

            if (dictDataDto != null && dictDataDto.getDictDataName() != null) {
                sourceBw.setPropertyValue(property.getName(), dictDataDto.getDictDataName());
            }
        }
    }

    private DictDataDto getContsDictData(Object fieldValue, DictDataDto dictDataDto, Class clz, BeanWrapper sourceBw, String propName) {
        try {
            Method method = null;
            String name = "value";  //这个位置就很神，竟然是写死的；
            Object methodValue = null;
            Class valueClz = null;

            try {
                method = clz.getMethod(name, Integer.class);
                valueClz = Integer.class;
            } catch (NoSuchMethodException var16) {
                try {
                    method = clz.getMethod(name, String.class);
                    valueClz = Integer.class;
                } catch (NoSuchMethodException var15) {
                    try {
                        method = clz.getMethod(name, Long.class);
                        valueClz = Long.class;
                    } catch (NoSuchMethodException var14) {
                        throw new RuntimeException("未获取到static value方法", var14);//??
                        // throw BusinessRtException.of("未获取到static value方法", var14);
                    }
                }
            }

            if (valueClz != null) {
                try {
                    if (!(fieldValue instanceof List) && !sourceBw.getPropertyType(propName).isAssignableFrom(List.class)) {
                        if (fieldValue != null) {
                            methodValue = method.invoke((Object)null, valueClz.getMethod("valueOf", String.class).invoke((Object)null, String.valueOf(fieldValue)));
                        }
                    } else {
                        List fieldListValue = null;
                        if (!(fieldValue instanceof Long) && !(fieldValue instanceof Integer)) {
                            if (fieldValue instanceof List) {
                                fieldListValue = (List)fieldValue;
                            }
                        } else {
                            fieldListValue = BinaryNumberUtils.splitToInt(Long.parseLong(String.valueOf(fieldValue)));
                        }

                        if (CollectionUtils.isNotEmpty((List)fieldValue)) {
                            Object mValue;
                            for(Iterator var11 = ((List)fieldValue).iterator(); var11.hasNext(); fieldListValue.add(mValue)) {
                                Object value = var11.next();
                                mValue = method.invoke((Object)null, valueClz.getMethod("valueOf", String.class).invoke((Object)null, String.valueOf(value)));
                                if (mValue == null) {
                                    mValue = String.valueOf(value);
                                }
                            }

                            methodValue = fieldListValue;
                        }
                    }
                } catch (NoSuchMethodException var17) {
                    log.info("字段不是基础类型[Integer，Long，String]");
                }
            }

            if (methodValue != null) {
                dictDataDto = new DictDataDto();
                dictDataDto.setVal(fieldValue);
                dictDataDto.setDictDataName(methodValue);
            }
        } catch (RuntimeException var18) {
        // } catch (BusinessRtException var18) {
            log.info("error:{}参数没有value方法", clz.getName(), var18);
        } catch (IllegalAccessException var19) {
            log.info("error:{}参数没有value方法调用失败", clz.getName(), var19);
        } catch (InvocationTargetException var20) {
            log.info("error:{}参数没有value方法调用失败", clz.getName(), var20);
        }

        return dictDataDto;
    }
}
